package eu.web.frame.template;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

import eu.common.config.ConfigEngine;
import eu.common.toolkits.ResourceUtil;
import eu.web.frame.Constants;
import eu.web.frame.WebAppContext;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModelException;

/**
 * 页面上下文，在使用之前必须调用init()方法执行初始化。
 * 
 * @author WZZ
 * 
 */
public class PageContext {

	/**
	 * FreeMaker 数据模板
	 */
	private static ThreadLocal<Map<String, Object>> param = new ThreadLocal<Map<String, Object>>();

	/**
	 * 私有参数列表
	 */
	private static ThreadLocal<Map<String, Object>> privateContext = new ThreadLocal<Map<String, Object>>();

	/**
	 * 
	 */
	private static Configuration tplCfg = null;

	/**
	 * 上下文
	 */
	private static final PageContext instance = new PageContext();

	/**
	 * 获取实例
	 * 
	 * @return
	 */
	public static PageContext getInstance() {
		return instance;
	}

	private PageContext() {
	}

	/**
	 * 
	 * @author WZZ
	 * 
	 */
	private interface Keys {

		String TEMPLATE = "template";

		String THEME = "theme";

		String CONTEXT_KEY = "context";

		String STATICS_TYPE = "STATICS_TYPE";
		
		String STATICS_ID = "STATICS_ID";
	}

	public static void initContext() {
		// 初始化模板引擎
		try {
			tplCfg = new Configuration();
			tplCfg.setDirectoryForTemplateLoading(new File(WebAppContext.getConfig(Constants.CONFIG.TEMPLATE_PATH)));
			tplCfg.setObjectWrapper(new DefaultObjectWrapper());
			if (WebAppContext.containsConfig(Constants.CONFIG.TEMPLATE_ENCODING))
				tplCfg.setDefaultEncoding(WebAppContext
						.getConfig(Constants.CONFIG.TEMPLATE_ENCODING));
			tplCfg.setDateTimeFormat("yyyy-MM-dd HH:mm:ss");
			tplCfg.setDateFormat("yyyy-MM-dd");
			tplCfg.setNumberFormat("##0");
			ConfigEngine engine = ConfigEngine.getEngine(ConfigEngine.EngineType.XMLEngine, 
					ResourceUtil.getResourcePath("conf/runtime/web.template.xml"),"UTF-8");
			// 解析配置文件
			for (String name : engine.getSubNames("/template/extension-function")) {
				try {
					tplCfg.setSharedVariable(name, 
							Class.forName(engine.getValue("/template/extension-function/" + name)).newInstance());
				} catch (Exception e) {
					e.printStackTrace();
					continue;
				}
			}
			tplCfg.setSharedVariable(Keys.CONTEXT_KEY, instance);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (TemplateModelException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 初始化页面上下文
	 */
	public static void init() {
		PageContext.privateContext.set(new HashMap<String, Object>());
		PageContext.param.set(new HashMap<String, Object>());
	}

	public static void setTheme(String theme) {
		PageContext.privateContext.get().put(Keys.THEME, theme);
	}

	public static void setTemplate(String template) {
		PageContext.privateContext.get().put(Keys.TEMPLATE, template);
	}

	public static void turnStaticsSwitch(int type, int id) {
		privateContext.get().put(Keys.STATICS_TYPE, type);
		privateContext.get().put(Keys.STATICS_ID, id);
	}
	
	public String getTemplate() {
		return (String) PageContext.privateContext.get().get(Keys.TEMPLATE);
	}

	public String getTheme() {
		String theme = (String) PageContext.privateContext.get()
				.get(Keys.THEME);
		if (theme == null) {
			theme = WebAppContext.getConfig(Constants.CONFIG.SYS_THEME);
		}
		return theme;
	}

	public String getAppBase() {
		return WebAppContext.getAppBase();
	}

	public String getThemeBase() {
		return getAppBase()
				+ WebAppContext.getConfig(Constants.CONFIG.TEMPLATE_DIR)
				+ "/" + getTheme() + "/";
	}

	/**
	 * 放置参数
	 * 
	 * @param name
	 * @param param
	 */
	public static void putParam(String name, Object param) {
		PageContext.param.get().put(name, param);
	}

	/**
	 * 放置参数
	 * 
	 * @param params
	 */
	public static void putParam(Map<String,? extends Object> params) {
		PageContext.param.get().putAll(params);
	}


	/**
	 * 输出页面
	 * 
	 * @param out
	 * @throws IOException 
	 * @throws TemplateException 
	 */
	public static void flush(Writer out) throws IOException, TemplateException {
		Template tpl = getTemplate(instance.getTheme() + instance.getTemplate());
		if (privateContext.get().get(Keys.STATICS_TYPE) != null) {
			// TODO 做一个更新同步锁
			Writer writer = new StringWriter();
			tpl.process(param.get(), writer);
			out.write(writer.toString());
		} else {
			tpl.process(param.get(), out);
		}
	}

	/**
	 * 获取模板
	 * 
	 * @param path
	 * @return
	 * @throws IOException
	 */
	private static Template getTemplate(String path) throws IOException {
		return tplCfg.getTemplate(path);
	}

}
